/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.server;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.bioteam.appweb.Config;
import net.bioteam.common.user.User;
import net.sf.gilead.core.store.IProxyStore;
import net.sf.gilead.core.store.stateful.HttpSessionProxyStore;

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class MyRemoteServiceServlet extends RemoteServiceServlet
{
	private static final long serialVersionUID = 1L;

	@Override
	protected void doUnexpectedFailure(Throwable e)
	{
		try
		{
			throw e;
		} catch (MyAuthException e1)
		{
			HttpServletResponse response = getThreadLocalResponse();
			try
			{
				response.setContentType("text/plain");
				response.setStatus(e1.getCode());
				response.getWriter().write(e1.getMessage());
			} catch (IOException ex)
			{
				log("respondWithUnexpectedFailure failed while sending the previous failure to the client", ex);
			}

		} catch (Throwable e2)
		{
			Exception e3=new Exception(e2.getMessage());
			super.doUnexpectedFailure(e3);
		}

	}

	@Override
	public String processCall(String payload) throws SerializationException
	{
		doAuthcheck();
		IProxyStore ips=Config.beanManager.getProxyStore();
		if (ips instanceof HttpSessionProxyStore)
		{
			 HttpSessionProxyStore.setHttpSession(getThreadLocalRequest().getSession(true));
		} 
		try
		{
			return super.processCall(payload);
		} finally
		{
			if (ips instanceof HttpSessionProxyStore)
				HttpSessionProxyStore.setHttpSession(null);
		}
	}

	/**
	 * Check authentication and authorization. throw Runtime Error if needed.
	 */
	public void doAuthcheck()
	{
		HttpServletRequest req = getThreadLocalRequest();
		String requestURI = req.getRequestURI();
		int index = requestURI.indexOf('/', 1);
		requestURI = requestURI.substring(index);
		if (req.getRequestedSessionId() != null && !req.isRequestedSessionIdValid())
		{
			throw new MyAuthException(499, "Session expired. Please logout and re-login");
		}
		// need authentication
		HttpSession session = req.getSession(true);
		if (requestURI.startsWith("/apps/user") || requestURI.startsWith("/apps/admin"))
		{
			// not logged in
			if (session.getAttribute("username") == null)
			{
				throw new MyAuthException(HttpServletResponse.SC_UNAUTHORIZED, "Please login first");
			} else
			{
				String role = getUserRole((String) session.getAttribute("username"));
				if (!role.equals("admin") && requestURI.startsWith("/apps/admin"))
				{
					throw new MyAuthException(HttpServletResponse.SC_FORBIDDEN, "You do not have the Permission to access this resource");
				}
			}
		}
	}

	/**
	 * 
	 * @param username
	 * @return user role: used for authorization.
	 */
	protected String getUserRole(String username)
	{
		User user=(User)this.getThreadLocalRequest().getSession().getAttribute("user");
		return user.getRole();
	}

}
